<?php
namespace app\index\controller;

use app\Lib\Exception\BlException;
use app\Lib\Exception\SysException;
use app\Lib\InterfaceIn\Api\Api;
use app\Lib\Ioc\Systems\TopClient;
use app\Lib\Model\Systems\FileLog;
use app\Lib\Model\Systems\RequestParam;
use think\Config;
use think\Request;

class Index
{
    private static $log = [];
    private $param;

    public function index()
    {
        $control="";
        $requestParam = '';
        try {
            $requestParam = new RequestParam();
            $requestParam->requestId = $this->create_uuid();//请求id
            $requestParam->startTime = microtime(true);
            $this->param = $requestParam;
            $request = Request::instance();
            $top = new TopClient($request, $requestParam);
            $top->check();
            $method = $requestParam->method;
            $control =$method;
            $class = 'app\index\interfaceIn\\' . lcfirst($control);
            if (!class_exists($class)) throw new SysException("接口方法($class)不存在");


            $object = new $class($requestParam);
            if (!($object instanceof Api)) throw new SysException("不规范接口");

            $object->handle();
            if ($requestParam->return === null) throw new SysException("接口返回数据不规范");
            $result = $this->output($requestParam->return);
            //$this->behaviorLog($control,$requestParam,1,$result);
            return $result ;
        } catch (SysException $e) {
            return $this->do_exception($e,$control,$requestParam);
        } catch (BlException $e) {
            $errorCode = null !== $e->getCode() ? $e->getCode() : 0;
            $result =  $this->errorOutput($errorCode, $e->getMessage(), $e->getMessage());
            //$this->behaviorLog($control,$requestParam,0,$result);
            return $result;
        } catch (\Exception $e) {
            return $this->do_exception($e,$control,$requestParam);
        }
    }

    /**
     * 处理异常
     * @param \Exception $e
     * @param $control
     * @param $requestParam
     * @return string
     */
    private function do_exception(\Exception $e,$control,$requestParam)
    {
        $errorCode = null !== $e->getCode() ? $e->getCode() : 0;
        $file=$e->getFile();
        $line=$e->getLine();
        foreach ($e->getTrace() as $Trace) {
            if(isset($Trace['file']) && strpos($Trace['file'],THINK_PATH) === false){
                $file=$Trace['file'];
                $line=$Trace['line'];
                break;
            }
        }

        $msg=Config::get("app_debug")?$e->getMessage()."file:".$file.",line".$line:"系统异常";

        $result = $this->errorOutput($errorCode,$msg, $e->getMessage());
        //$this->behaviorLog($control,$requestParam,0,$result);
        return $result;
    }

//    public function getApiName($method, $version)
//    {
//        $docx = new DocxApi();
//        $docx->method = $method;
//        $docx->version = $version;
//        $docx->getApiNameByMethod();
//        $apiInfo = $docx->ApiInfo;
//        $class = isset($apiInfo) && $apiInfo ? $apiInfo['class'] : $method;
//
//        return $class;
//    }


    public function output($data = [], $status = 1, $message = "请求成功")
    {
        $return = [
            "requestId" => $this->param->requestId,
            "code" => 1,
            "result" => [
                "status" => $status,
                "message" => $message,
                "data" => $data
            ]
        ];
        $this->file_log($this->param->postData, $return);
        return json_encode($return);
    }

    public function errorOutput($errorCode, $errorMessage, $realMessage = "")
    {
        $return = [
            "requestId" => $this->param->requestId,
            "code" => 0,
            "result" => [
                "status" => $errorCode,
                "message" => $errorMessage
            ]
        ];
        $returnJson = json_encode($return);
        $return['result']['message'] = $realMessage;//当有些系统错误无需返回给用户端时候，日志记录真实的错误
        $this->file_log($this->param->postData, $return);
        return $returnJson;
    }

    public function file_log($data = [], $return = [])
    {
        $msg = "[requestId:" . $this->param->requestId . ']' . "[postdata:" . json_encode($data) . ']' . "[return:" . json_encode($return) . "]";
        self::$log = ["logic" => ["no" => $msg]];
        self::write($msg);
    }

    public static function write($msg, $type = 'log', $force = false)
    {
        $log = self::$log;
        $config = ["path" => LOG_PATH . 'ApiLogs/'];
        // 写入日志
        $result = (new FileLog($config))->save($log);
        if ($result) {
            self::$log = [];
        }
        return $result;
    }

    private function create_uuid($prefix = "")
    {
        $str = md5(uniqid(mt_rand(), true));
        $uuid = substr($str, 0, 8) . '-';
        $uuid .= substr($str, 8, 4) . '-';
        $uuid .= substr($str, 12, 4) . '-';
        $uuid .= substr($str, 16, 4) . '-';
        $uuid .= substr($str, 20, 12);
        return $prefix . $uuid;
    }
}
